#ifndef __RAYTRACER_IMAGE_FACTORY_HXX__
#define __RAYTRACER_IMAGE_FACTORY_HXX__

#include "imagefactory.h"

#include <iostream>

namespace raytracer {

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> >
ImageFactory::mCreate(
   const size_t &a_width,
   const size_t &a_height)
{
   return boost::make_shared< Image<DataType,PixelType> >(
      a_width,a_height);
}

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> > ImageFactory::mCreate()
{
   return boost::make_shared< Image<DataType,PixelType> >();
}

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> > ImageFactory::create(
   const size_t &a_width,
   const size_t &a_height)
{
   return instance().mCreate<DataType,PixelType>(a_width,a_height);
}

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> > ImageFactory::create()
{
   return instance().mCreate<DataType,PixelType>();
}

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> > ImageFactory::create(
   const std::string &a_filename)
{
   instance().mLoad<DataType,PixelType>(a_filename);
}

template<typename DataType, typename PixelType>
bool ImageFactory::save(
   const boost::shared_ptr< Image<DataType, PixelType> > &a_image,
   const std::string &a_filename)
{
   return instance().mSave(a_image,a_filename);
}

template<typename DataType>
boost::shared_ptr< Image<DataType,rgb_t> > ImageFactory::create(
   const size_t &a_width,
   const size_t &a_height)
{
   return instance().mCreate<DataType,rgb_t>(a_width,a_height);
}

template<typename DataType>
boost::shared_ptr< Image<DataType,rgb_t> > ImageFactory::create()
{
   return instance().mCreate<DataType,rgb_t>();
}

template<typename DataType>
boost::shared_ptr< Image<DataType,rgb_t> > ImageFactory::create(
   const std::string &a_filename)
{
   return instance().mLoad<DataType,rgb_t>(a_filename);
}

template<typename DataType>
bool ImageFactory::save(
   const boost::shared_ptr< Image<DataType, rgb_t> > &a_image,
   const std::string &a_filename)
{
   return instance().mSave(a_image,a_filename);
}

template<typename DataType, typename PixelType>
boost::shared_ptr< Image<DataType,PixelType> > ImageFactory::mLoad(
   const std::string &a_filename)
{
   boost::shared_ptr< Image<DataType,PixelType> > l_result;

   if( this->mLoadDataBuffer(
      a_filename,PixelType::gflColorModel()) ) {

      l_result = mCreate<DataType,PixelType>(
         m_info.Width,m_info.Height);

      std::copy(
         m_data->Data,
         m_data->Data+l_result->size(),
         l_result->begin());

   }
   this->mClearDataBuffer();
   return l_result;
}

template<typename DataType, typename PixelType>
bool ImageFactory::mSave(
   const boost::shared_ptr< Image<DataType,PixelType> > &a_image,
   const std::string &a_filename)
{
   this->mCreateDataBuffer(
      a_image->width(),a_image->height(),PixelType::gflColorModel());

   std::copy(
      a_image->begin(),
      a_image->end(),
      m_data->Data);

   bool l_result(this->mSaveDataBuffer(a_filename));

   mClearDataBuffer();

   return l_result;
}

} //end of namespace

#endif //__RAYTRACER_IMAGE_FACTORY_HXX__
